When a program (software) is executed on a central processing unit (hardware), it is generally expected that the program will actually also be executed in the manner intended by the compiler at the compiling time. In reality, however, the execution of a program or of a code can deviate from the program sequence originally planned. By way of example, faults in the hardware, interference signals or else targeted, malicious manipulations on the central processing unit can be responsible for this. Faults in the hardware can be attributed, for example, to undesired line short circuits, line interruptions or hung switching elements (so-called “stuck-at faults”), to name a few frequently occurring types of hardware faults. Interference signals can occur during the operation of the central processing unit for example as a result of electromagnetic fields or else in the form of extreme temperatures lying outside the temperature range provided for the central processing unit. Malicious manipulations of the hardware can be effected for example by the short-circuiting of selected contacts, line interruptions or laser irradiation of the central processing unit and/or of a memory connected to the central processing unit. The types of faults mentioned can occur for example within the central processing unit itself, within a memory in which the program is stored, within further components of a system comprising the central processing unit, or in electrical connections between the components of the computer system. In order to detect such faults during the execution of the program, an instruction flow supervision can be carried out.
For the purposes of the instruction flow supervision, a check value resulting from the instructions of the program to the central processing unit is generally calculated during the program creation. By way of example, it is possible to add the operation codes (opcodes) of the instructions in order in this way to form a checksum. In the case of a linear program, which is generally executed from the beginning of the program to the end of the program including all intervening instructions, it is thus possible to calculate a single checksum (or more generally a check value), which can be checked at the end of the program or after the end of the program. For this check, in parallel with the execution of each instruction by the central processing unit, the value of the instruction (for example in the form of the opcode present as a bit pattern) is taken into account computationally with the content of a specific register, e.g. added to the register content or logically combined with the register content bit by bit using an exclusive-or (XOR) operation. As soon as all the instruction values have been taken into account in this way in the specific register, the resulting value of the specific register can be compared with a reference check value in order to ascertain whether there is a match between the two values. If there is a match, proper execution of the program can generally be assumed, that is to say that the program has actually been executed in the manner planned at the point in time of program creation. The reference check value can be stored for example as a constant in the program code. Depending on how and in what programming language the program was created, the reference check value can be calculated by a compiler and written into the program code.
Programs often have branches in the program flow, which can also be regarded as “conditional jumps”. After a branch, the program can be continued on at least two paths, the decision about which of the two or more possible paths is chosen arising only at the running time of the program through the evaluation of a condition. It should be noted that branch points with more than two possible branch paths can generally be divided into elementary branch points, i.e. into branch points each having only two possible branch paths. For the value calculated during the running time of the program, this means that it is dependent on which paths were traversed how often. In order that for example toward the end of the program or at some other point within the program sequence, a comparison between the current check value and a reference check value defined for the point can be carried out, there is the possibility of mutually orienting the check value within the different paths can that be traversed. This can be effected in a form such that the compiler incorporates into one path one or more instruction(s) inherently superfluous for the program sequence, the instruction(s) altering the check value in such a way that the path, at a junction point with another path, has the same check value as this other path.
Besides branch points which occur within a program and are defined by the code of the program, it can also happen that the processing of the program by the central processing unit is temporarily interrupted in order to execute or continue another program. Such an interruption is designated by the term “interrupt”. A further possibility, of which use is made relatively frequently in the programming of programs for computer systems and similar systems, consists in a specific program calling a function present in another program (for example a program library (“software library”)). Since the function or subroutine defined in the program library was not usually compiled jointly with the main program, it is generally not possible to include the subroutine in the check value calculation of the main program. If an instruction flow supervision is also intended to be carried out for the subroutine or subprogram, then the subroutine can be tested separately using a dedicated check value. The check value of the subprogram is thus independent of the check value of the main program. Faults which occur in connection with a change in the central processing unit from processing the main program to processing the subprogram, or vice versa, often remain undiscovered.